#include "precompiled.h"
#include "optimization.h"
using namespace weo::engine::optimization;
using namespace weo::engine::character;
using namespace weo::engine::item;
using namespace std;
Optimization::Optimization()
{
    memset(m_Locked,0,weo::engine::Slotcount*sizeof(bool));
    m_Abort = false;
}
void Optimization::setItems(const std::vector<std::vector<const weo::engine::item::Item*>>& items)
{
    m_Items = filterOptimizeItems(items);
    m_Gemindex = weo::engine::Slotcount;
}
// basically we check for each item, if there is a nother item with same basic attributes, but with higher values and such reduce the item count
// socketed items or items with sets are always included
vector<vector<const Item*>> Optimization::filterOptimizeItems(const vector<vector<const Item*>>& value)
{
    vector<vector<const Item*>> retval;
    vector<vector<const Item*>>::const_iterator it1;
    vector<const Item*>::const_iterator it2;
    vector<const Item*>::const_iterator it3;
    for(it1 = value.begin(); it1 != value.end();it1++)
    {
        vector<const Item*> temp;
        for(it2 = it1->begin();it2 != it1->end();it2++)
        {
            bool add = true;
            const Item* item = *it2;
            for(it3 = it2+1;it3!=it1->end();it3++)
            {
                const Item* item2 = *it3;
                if(!add) break;
                if(
                    item->Attributes()->size() != item2->Attributes()->size() ||
                    item->Unique() != item2->Unique() ||
                    item->DPS() != item2->DPS() ||
                    item->Speed() != item2->Speed() ||
                    item->Type() != item2->Type() ||
                    item->Slot() != item2->Slot() ||
                    item->Subtype() != item2->Subtype() ||
                    item->Allowed() != item2->Allowed() ||
                    item->Sockets()->Count() > 0 ||
                    !item->Set()->Item()->empty()
                    )
                {
                    continue;
                }
                else
                {
                    add = false;
                    for(unsigned int i = 0;i<item->Attributes()->size();i++)
                    {
                        bool matchedattr = false;
                        if(item->Attributes()->at(i).Type() == 45)
                        {
                            add = true;
                            break;
                        }
                        for(unsigned int k = 0;k<item2->Attributes()->size();k++)
                        {
                            if(item->Attributes()->at(i).Type() == item2->Attributes()->at(k).Type())
                            {
                                if(item->Attributes()->at(i).Value() <= item2->Attributes()->at(k).Value())
                                {
                                    matchedattr = true;
                                }
                            }
                        }
                        if(!matchedattr)
                        {
                            add = true;
                            break;
                        }
                    }
                }
            }
            if(add && item->Id() != 99999)
            {
                temp.push_back(*it2);
            }
        }
        if(temp.empty())
        {
            temp.push_back(Item::None());
        }
        retval.push_back(temp);
    }
    return retval;
}
inline bool Optimization::Valid(ItemPtr items[weo::engine::Slotcount],GemPtr gems[weo::engine::Slotcount], EnchantPtr enchants[weo::engine::Slotcount])
{
    // finger
    if(items[10]->Unique() && items[11]->Unique())
    {
        if(items[10]->Id() == items[11]->Id()) return false;
        else if(items[10]->Id() <= 29291 && items[11]->Id() >= 29276 && items[11]->Id() <= 29291 && items[11]->Id() >= 29276) return false;		//violet signet quest ring
        else if(items[10]->Id() <= 29309 && items[11]->Id() >= 29294 && items[11]->Id() <= 29309 && items[11]->Id() >= 29294) return false;		//band of eternity questring
    }
    // trinkets
    if(items[12]->Unique() && items[13]->Unique())
    {
        if(items[12]->Id() == items[13]->Id()) return false;		
    }
    // weapons
    if(items[14]->Unique() && items[15]->Unique())
    {
        if(items[14]->Id() == items[15]->Id()) return false;
    }
    if(items[14]->Slot() == 4 && items[15]->Id() != 99999) return false;
    // two hand weapon
    if(items[14]->Slot() == 4)
    {
        items[15] = Item::None();
        gems[15*3] = 0;
        gems[15*3+1] = 0;
        gems[15*3+2] = 0;
        enchants[15] = 0;
    }
    bool goodmeta = weo::engine::item::Item::CheckMetaGemRequirements(gems);
    if(!goodmeta) return false;
    if(m_StartLoop.elapsed() > 10) m_Abort = true;
    return !m_Abort;
}
const Enchant* Optimization::getEnchant(const Item& item, unsigned int slot)
{
    if(item.Type() == 1 && item.Slot() == 11)
    {
        return weo::engine::item::Enchant::GetEnchant(18);
    }
    else if(item.Type() == 4 && item.Slot() == 4)
    {
        return weo::engine::item::Enchant::GetEnchant(17);
    }
    else if(item.Type() == 1 && item.Slot() == 12)
    {
        return NULL;
    }
    else
    {
        return weo::engine::item::Enchant::GetEnchant(slot);
    }
}
void Optimization::populateSlot(ItemPtr& item, GemPtr& gem1, GemPtr& gem2, GemPtr& gem3, EnchantPtr& enchant, int slot, int number)
{
    if(m_Items[slot].empty()) return;
    if(number == 0)
    {
        number = std::rand() % m_Items[slot].size();
    }
    item = m_Items[slot][number];
    GemPtr *gems[3] = {&gem1,&gem2,&gem3};
    for(unsigned int j = 0;j<3;j++)
    {
        *gems[j] = 0;
        if(j<item->Sockets()->Count())
        {					
            while(true)
            {
                const Item* gem = m_Items[m_Gemindex][std::rand() % m_Items[m_Gemindex].size()];
                if(item->Sockets()->Colors()->at(j) == 8 && gem->Subtype() != 8) continue;
                else if(item->Sockets()->Colors()->at(j) != 8 && gem->Subtype() == 8) continue;
                else *gems[j] =  gem;
                break;
            }
        }
    }
    enchant = getEnchant(*item,slot);
}
Optimization::~Optimization()
{
}